<template>
  <a-drawer
    title="文件管理器"
    placement="right"
    width="900"
    :closable="false"
    :visible="visible"
    :after-visible-change="onShow"
    @close="v => this.visible = false"
  >
    <input style="display: none" type="file" :ref="this.input"/>
    <div class="drawerHeader">
      <a-breadcrumb>
        <a-breadcrumb-item href="#">
          <a-icon type="home" @click="handleChdir('','0')"/>
        </a-breadcrumb-item>
        <a-breadcrumb-item href="#" :key=item v-for="item in this.state.pwd">
          <span @click="handleChdir(item,'2')">{{ item }}</span>
        </a-breadcrumb-item>
      </a-breadcrumb>
      <div style="display: flex;align-items: center">
        <span>显示隐藏文件：</span>
        <a-switch checked-children="开启" un-checked-children="关闭" :checked="state.showDot"
                  @change="(v) => state.showDot = v"/>
        <a-upload
          :showUploadList="false"
          :before-upload="beforeUpload"
          @change="handleUpload">
          <a-button type="primary" style="margin-left: 10px" size="small">
            <a-icon type="upload"/>
            点击上传
          </a-button>
        </a-upload>
      </div>
    </div>
    <a-progress v-if="state.uploading === true" :percent="state.percent" :status="state.uploadStatus" style="margin-bottom: 15px"/>
    <a-table
      size="middle"
      :rowKey="(record) => record.name"
      :pagination="false"
      :loading="this.state.fetching"
      :columns="columns"
      :data-source="tableData()"
      style="font-family: Source Code Pro, Courier New, Courier, Monaco, monospace, PingFang SC, Microsoft YaHei"
    >
      <span slot="name" slot-scope="text, record">
        <template>
          <div v-if="record.kind === 'd'" @click="handleChdir(record.name, '1')" style="cursor: pointer">
            <a-icon type="folder" :style="{color: record.is_link ? '#008b8b' : '#1890ff'}"/>
            <span :style="{color: record.is_link ? '#008b8b' : '#1890ff', 'padding-left': '5px'}">{{ text }}</span>
          </div>
          <div v-else>
            <a-icon type="file"/>
            <span style="padding-left: 5px">{{ text }}</span>
          </div>
        </template>
      </span>
      <span slot="action" slot-scope="text, record">
        <template>
          <div v-if="record.kind === '-'">
            <a-icon type="download" style="color: #1890ff" @click="handleDownload(record.name)"/>
            <a-divider type="vertical"/>
            <a-icon type="delete" style="color: red" @click="handleDelete(record.name)"/>
          </div>
        </template>
      </span>
    </a-table>
  </a-drawer>
</template>
<script>
  import { STable } from '@/components'
  import * as api from '@/api/main/file'
  import  lds from 'lodash'
  import { message } from 'ant-design-vue'
  import Vue from 'vue'
  import { ACCESS_TOKEN } from '@/store/mutation-types'
  import { mapGetters } from 'vuex'
  import { uniqueId } from '@/utils/util'

  const columns = [{
    title: '名称',
    key: 'name',
    dataIndex: 'name',
    scopedSlots: { customRender: 'name' },
    ellipsis: true
  }, {
    title: '大小',
    dataIndex: 'size',
    align: 'right',
    // className: fileSize,
    width: 90
  }, {
    title: '修改时间',
    dataIndex: 'date',
    width: 190
  }, {
    title: '属性',
    dataIndex: 'code',
    width: 110
  }, {
    title: '操作',
    width: 100,
    align: 'center',
    dataIndex: 'kind',
    scopedSlots: { customRender: 'action' }
  }]

  export default {
    name: 'FileManager',
    components: {
      STable
    },
    props: {
      id: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        visible: false,
        input: 'hjk',
        columns,
        objects: [],
        state: {
          fetching: false,
          showDot: false,
          uploading: false,
          uploadStatus: 'active',
          pwd: [],
          objects: [],
          percent: 0
        }
      }
    },
    computed: {
      ...mapGetters(['token'])
    },
    methods: {
      open() {
        this.visible = true
      },
      tableData(){
        if (!this.state.showDot) {
           return this.state.objects.filter(x => !x.name.startsWith('.'))
        } return this.state.objects
      },
      fetchFiles(pwd) {
        this.$set(this.state, 'fetching', true)
        pwd = pwd || this.state.pwd
        const path = '/' + pwd.join('/')
        api.getObj({ id: this.id, path: path })
          .then(res => {
            if (res.success) {
              const objects = lds.orderBy(res.data, [this._kindSort,'name'], ['desc', 'asc'])
              this.state.objects = objects
            }
          })
          .finally(() => this.$set(this.state, 'fetching', false))
      },
      _kindSort(item) {
        return item.kind === 'd'
      },
      handleChdir(name, action) {
        let pwd = this.state.pwd.map(x => x)
        if (action === '1') {
          pwd.push(name)
        } else if (action === '2') {
          const index = pwd.indexOf(name)
          pwd = pwd.splice(0, index + 1)
        } else {
          pwd = []
        }
        this.state.pwd = pwd
        this.fetchFiles(pwd)
      },
      beforeUpload(file) {
        return false
      },
      handleUpload(e) {
        this.setState({ uploading: true, uploadStatus: 'active', percent: 0 })
        const file = e.file
          const formData = new FormData()
          const token = uniqueId()
          this._updatePercent(token)
          formData.append('file', file)
          formData.append('id', this.id)
          formData.append('token', token)
          formData.append('path', '/' + this.state.pwd.join('/'))
          api.uploadObj(formData,this._updateLocal)
            .then(() => {
              this.setState({ uploadStatus: 'success' })
              this.fetchFiles()
            }, () => this.setState({ uploadStatus: 'exception' }))
            .finally(() => setTimeout(() =>  this.setState({uploading: false}), 2000))
      },
      _updateLocal(e) {
        const percent = e.loaded / e.total * 100
        this.setState({percent: Number(percent.toFixed(1))})
      },
      _updatePercent(token) {
        this.socket = new WebSocket(this._getWsUrl(token))
        this.socket.onopen = () => this.socket.send('ok')
        this.socket.onmessage = e => {
          if (e.data === 'pong') {
            this.socket.send('ping')
          } else {
            const percent = Number(e.data)
            if (percent > this.state.percent) {
              this.state.percent = percent
            }
            if (percent === 100) {
              this.socket.close()
            }
          }
        }
      },
      setState(params){
        for(const key in params){
          this.state[key] = params[key]
        }
      },
      // 获取websocket连接地址
      _getWsUrl(token) {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
        const urlFamily = window.location.host.split(':')
        const hostname = '127.0.0.1'
        // const hostname = urlFamily[0]
        let urlPort = urlFamily.length === 2 ? Number(urlFamily[1]) : null
        if (urlPort === 81) {
          urlPort = 9001
        }
        return `${protocol}//${hostname}${urlPort ? ':' + urlPort : ''}${urlPort !== 9001 ? '/api' : ''}/ws/exec/${token}/?x-token=${this.token}`
      },
      handleDownload(name) {
        const token = Vue.ls.get(ACCESS_TOKEN)
        const file = `/${this.state.pwd.join('/')}/${name}`
        const link = document.createElement('a')
        link.download = name
        link.href = `http://localhost:9001/system/file/object/?id=${this.id}&file=${file}&token=${token}`
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        message.warning('即将开始下载，请勿重复点击。')
      },
      handleDelete(name) {
        const file = `/${this.state.pwd.join('/')}/${name}`
        this.$confirm({
          title: '删除文件确认',
          content: `确认删除文件：${file} ?`,
          onOk: () => {
            api.deleteObj({ id: this.id, file })
              .then(() => {
                message.success('删除成功')
                this.fetchFiles()
              })
          }
        })
      },
      onShow(visible) {
        if (visible) {
          this.fetchFiles()
        }
      }
    }
  }
</script>
<style lang="less">
  .fileSize {
    padding-right: 24px !important;
  }

  .drawerHeader {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
  }
</style>